package sim

import (
	"context"
	"time"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/sagoo-cloud/sagooiot/internal/consts"
	"github.com/sagoo-cloud/sagooiot/internal/dao"
	"github.com/sagoo-cloud/sagooiot/internal/model"
	"github.com/sagoo-cloud/sagooiot/internal/service"
)

type sSimSimHistoryTraffic struct{}

func sSimSimHistoryTrafficNew() *sSimSimHistoryTraffic {
	return &sSimSimHistoryTraffic{}
}
func init() {
	service.RegisterSimSimHistoryTraffic(sSimSimHistoryTrafficNew())
}

// GetSimHistoryTrafficList 获取列表数据
func (s *sSimSimHistoryTraffic) GetSimHistoryTrafficList(ctx context.Context, in *model.GetSimHistoryTrafficListInput) (total, page int, list []*model.SimHistoryTrafficOutput, err error) {
	err = g.Try(ctx, func(ctx context.Context) {
		m := dao.SimHistoryTraffic.Ctx(ctx)

		if in.KeyWord != "" {
			m = m.Where(dao.SimHistoryTraffic.Columns().AccessNumber, in.KeyWord)
		}
		if in.Month != "" {
			m = m.Where("left(flow_day,6) = ? ", in.Month)
		}
		if in.Day != "" {
			m = m.Where(dao.SimHistoryTraffic.Columns().FlowDay, in.Day)
		}

		total, err = m.Count()
		if err != nil {
			err = gerror.New("获取总行数失败")
			return
		}
		page = in.PageNum
		if in.PageSize == 0 {
			in.PageSize = consts.PageSize
		}
		err = m.Page(page, in.PageSize).Order("flow_amount desc").Scan(&list)
		if err != nil {
			err = gerror.New("获取数据失败")
		}
	})
	return
}

// GetSimHistoryTrafficById 获取指定ID数据
func (s *sSimSimHistoryTraffic) GetSimHistoryTrafficById(ctx context.Context, id int) (out *model.SimHistoryTrafficOutput, err error) {
	err = dao.SimHistoryTraffic.Ctx(ctx).Where(dao.SimHistoryTraffic.Columns().Id, id).Scan(&out)
	return
}

// AddSimHistoryTraffic 添加数据
func (s *sSimSimHistoryTraffic) AddSimHistoryTraffic(ctx context.Context, in model.SimHistoryTrafficAddInput) (err error) {
	_, err = dao.SimHistoryTraffic.Ctx(ctx).Insert(in)
	return
}

// EditSimHistoryTraffic 修改数据
func (s *sSimSimHistoryTraffic) EditSimHistoryTraffic(ctx context.Context, in model.SimHistoryTrafficEditInput) (err error) {
	dao.SimHistoryTraffic.Ctx(ctx).FieldsEx(dao.SimHistoryTraffic.Columns().Id).Where(dao.SimHistoryTraffic.Columns().Id, in.Id).Update(in)
	return
}

// DeleteSimHistoryTraffic 删除数据
func (s *sSimSimHistoryTraffic) DeleteSimHistoryTraffic(ctx context.Context, Ids []int) (err error) {
	_, err = dao.SimHistoryTraffic.Ctx(ctx).Delete(dao.SimHistoryTraffic.Columns().Id+" in (?)", Ids)
	return
}

// TopFLow 仪表盘 流量排行
func (s *sSimSimHistoryTraffic) TopFLow(ctx context.Context, req *model.TopFlowIn) (res *model.TopFlowOut, err error) {
	res = new(model.TopFlowOut)
	err = dao.SimHistoryTraffic.Ctx(ctx).WhereBetween("created_at", req.Sdate, req.Edate).
		Where(dao.SimHistoryTraffic.Columns().Types, req.Types).
		Group(dao.SimHistoryTraffic.Columns().AccessNumber).
		Fields("sum(flow_amount) value,access_number ").
		OrderDesc("value").
		Limit(10).Scan(&res.Data)

	return
}

// SimHTrafficStatis 仪表盘统计数据
func (s *sSimSimHistoryTraffic) SimHTrafficStatis(ctx context.Context, types string) (res *model.SimHTrafficStatisRes, err error) {
	res = &model.SimHTrafficStatisRes{}

	// 当月消耗流量
	dao.SimRealTraffic.Ctx(ctx).Where(dao.SimRealTraffic.Columns().MonthDay, 1).Where(dao.SimRealTraffic.Columns().Types, types).
		Fields("sum(flow_amount) real_month_total").Scan(res)

	// 当日消耗流量
	dao.SimRealTraffic.Ctx(ctx).Where(dao.SimRealTraffic.Columns().MonthDay, 2).Where(dao.SimRealTraffic.Columns().Types, types).
		Fields("sum(flow_amount) real_day_total").Scan(res)

	// 昨日流量消耗
	dao.SimHistoryTraffic.Ctx(ctx).Where(dao.SimHistoryTraffic.Columns().Types, types).
		Fields("sum(flow_amount) yesterday_total").Scan(res)

	// 本年消耗流量
	var total float64
	dao.SimHistoryTraffic.Ctx(ctx).Where("left(flow_day,6) = ?", time.Now().Format("200601")).
		Where(dao.SimRealTraffic.Columns().Types, types).Fields("sum(flow_amount) total").Scan(&total)
	res.YearTotal = res.RealMonthTotal + total

	return
}

// QueryHistoryTrafficByDate 根据日期查询 流量记录，显示折线图,sim卡详情的折线图,仪表盘折线图
func (s *sSimSimHistoryTraffic) QueryHistoryTrafficByDate(ctx context.Context, sdate string, edate string, accNumber string, types int) (out []model.TopFlowData, err error) {
	stime, err := time.ParseInLocation("2006-01-02 15:04:05", sdate, time.Local)
	if err != nil {
		return
	}

	etime, err := time.ParseInLocation("2006-01-02 15:04:05", edate, time.Local)
	if err != nil {
		return
	}
	// 以供应商维度统计
	if accNumber == "" {
		// 大于一年的按月统计返回
		if etime.Sub(stime).Seconds() >= 365*86400 {
			dao.SimHistoryTraffic.Ctx(ctx).Where(dao.SimHistoryTraffic.Columns().Types, types).
				WhereBetween("flow_day", stime.Format("20060102"), etime.Format("20060102")).
				Group("left(flow_day,6)").Fields("sum(flow_amount) value,date_format(`flow_day`,'%Y-%m-%d') date").
				Scan(&out)
			out, err = s.fillMonth(out, sdate, edate, accNumber)
		} else {
			// 小于一年的返回每天流量、 日期
			// var first sim.TopFlowData
			// dao.SimRealTraffic.Ctx(ctx).Where(dao.SimRealTraffic.Columns().Types, types).
			// 	Where(dao.SimRealTraffic.Columns().MonthDay, 2).Group(dao.SimRealTraffic.Columns().MonthDay).
			// 	Fields("sum(flow_amount) value").Scan(&first)

			// first.Date = time.Now().Format("2006-01-02")

			var tmp []model.TopFlowData
			dao.SimHistoryTraffic.Ctx(ctx).Where(dao.SimHistoryTraffic.Columns().Types, types).
				WhereBetween("flow_day", stime.Format("20060102"), etime.Format("20060102")).Group("flow_day").
				Fields("sum(flow_amount) value,date_format(`flow_day`,'%Y-%m-%d') date").OrderDesc("created_at").Scan(&tmp)

			// out = append(out, first)
			out = append(out, tmp...)

			out, err = s.fillDate(out, sdate, edate, accNumber)
		}
	} else {
		// 单张sim卡维度统计
		// 大于一年的按月统计返回
		if etime.Sub(stime).Seconds() >= 365*86400 {
			dao.SimHistoryTraffic.Ctx(ctx).Where(dao.SimHistoryTraffic.Columns().AccessNumber, accNumber).
				WhereBetween("flow_day", stime.Format("20060102"), etime.Format("20060102")).
				Group("left(flow_day,6)").Fields("sum(flow_amount) value,date_format(`flow_day`,'%Y-%m-%d') date").
				Scan(&out)
			out, err = s.fillMonth(out, sdate, edate, accNumber)
		} else {
			// 小于一年的返回每天流量、 日期
			// var today entity.SimRealTraffic
			// dao.SimRealTraffic.Ctx(ctx).Where(dao.SimRealTraffic.Columns().AccessNumber, accNumber).
			// 	Where(dao.SimRealTraffic.Columns().MonthDay, 2).Scan(&today)
			// var first sim.TopFlowData
			// first.AcceccNumber = accNumber
			// first.Date = time.Now().Format("2006-01-02")
			// first.Value = gconv.Float64(today.FlowAmount)

			var tmp []model.TopFlowData
			dao.SimHistoryTraffic.Ctx(ctx).Where(dao.SimHistoryTraffic.Columns().AccessNumber, accNumber).
				WhereBetween("date_format(`flow_day`,'%Y-%m-%d %H:%i:%s')", sdate, edate).
				Fields("flow_amount value,access_number,date_format(`flow_day`,'%Y-%m-%d') date").OrderDesc("created_at").Scan(&tmp)

			// out = append(out, first)
			out = append(out, tmp...)

			out, err = s.fillDate(out, sdate, edate, accNumber)
		}
	}
	return
}
func (s *sSimSimHistoryTraffic) fillMonth(in []model.TopFlowData, sdate string, edate string, accNumber string) (out []model.TopFlowData, err error) {
	st, err := time.ParseInLocation("2006-01-02", sdate[0:7]+"-01", time.Local)
	if err != nil {
		return
	}
	et, err := time.ParseInLocation("2006-01-02", edate[0:7]+"-01", time.Local)
	if err != nil {
		return
	}

	var m []string
	s.calcMonth(st, et, &m)
	for _, v := range m {
		var tmp model.TopFlowData
		tmp.AcceccNumber = accNumber
		tmp.Date = v
		tmp.Value = 0
		for _, vv := range in {
			if vv.Date[0:7] == v {
				tmp.Value = vv.Value
			}
		}
		out = append(out, tmp)
	}

	return
}
func (s *sSimSimHistoryTraffic) calcMonth(t1, t2 time.Time, m *[]string) *[]string {
	if t1.AddDate(0, 1, 0).Unix() <= t2.Unix() {
		*m = append(*m, t1.Format("2006-01"))
		t1 = t1.AddDate(0, 1, 0)
		return s.calcMonth(t1, t2, m)
	}
	return m
}
func (s *sSimSimHistoryTraffic) fillDate(in []model.TopFlowData, sdate string, edate string, accNumber string) (out []model.TopFlowData, err error) {
	st, err := time.ParseInLocation("2006-01-02", sdate[0:10], time.Local)
	if err != nil {
		return
	}
	et, err := time.ParseInLocation("2006-01-02", edate[0:10], time.Local)
	if err != nil {
		return
	}

	for i := et.Unix(); i >= st.Unix(); i = i - 86400 {
		var tmp model.TopFlowData
		tmp.AcceccNumber = accNumber
		tmp.Date = time.Unix(i, 0).Format("2006-01-02")
		tmp.Value = 0
		for _, v := range in {
			dt, err := time.ParseInLocation("2006-01-02", v.Date[0:10], time.Local)
			if err != nil {
				return nil, err
			}
			if i == dt.Unix() {
				tmp.Value = v.Value
			}
		}
		out = append(out, tmp)
	}
	return
}
